package cn.piesat.client.service.impl;

import cn.piesat.client.constant.cache.LocalCache;
import cn.piesat.client.constant.consist.AppProperties;
import cn.piesat.client.converter.QsClientRunnerConverter;
import cn.piesat.client.converter.QsEnterDataConverter;
import cn.piesat.client.model.dto.base.algorithm.DMSClientBean;
import cn.piesat.client.model.dto.base.task.DefaultRequestDto;
import cn.piesat.client.model.dto.buiness.QsClientRunnerDto;
import cn.piesat.client.model.vo.QsEnterDataVo;
import cn.piesat.client.service.ClientProcessIntf;
import cn.piesat.client.service.RedisSateService;
import cn.piesat.client.utils.FileWriteUtil;
import cn.piesat.client.utils.ProcCmd;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class QsProcessIntf implements ClientProcessIntf<DefaultRequestDto, QsClientRunnerDto> {
    private Logger logger = LoggerFactory.getLogger(QsProcessIntf.class);

    @Autowired
    private QsClientRunnerConverter qsClientRunnerConverter;

    @Autowired
    private QsEnterDataConverter qsEnterDataConverter;

    @Autowired
    private AppProperties appProperties;
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    @Autowired
    private RedisSateService redisSateService;

    @Value("${spring.kafka.xzdy.enterdata.topic}")
    private String xzdyEnterDataTopic;
    @Override
    public QsClientRunnerDto beforeProcess(DefaultRequestDto defaultRequestDto) {
        DMSClientBean dmsClientBean = LocalCache.algorithmCache.get(defaultRequestDto.getBasic().getAlgorithmIdentify());
        JSONObject json=(JSONObject) JSONObject.toJSON(defaultRequestDto.getOther());

        String paramString="";
        String exectxtFilePath = "";
        String resultJsonFilePath = "";
        String resultLogFilePath="";
        String resultFlowFilePath="";
        String execJsonFilePath = "";
        JSONObject jsonObject = null;
        if(dmsClientBean != null) {
            //20210518 时间
            String fileDate = defaultRequestDto.getBasic().getFileDate().substring(0, 8);
            //SWAPDSTDET 标识
            String adsType = defaultRequestDto.getBasic().getAlgorithmIdentify();
            //FY4A-_AGRI--_N_DISK_1047E_L1-_FDI-_MULT_NOM_20210518234500_20210518235959_4000M_V0001.HDF 文件名称（加后缀）
            String fileName = defaultRequestDto.getBasic().getMainFileName();
            //FY4A-_AGRI--_N_DISK_1047E_L1-_FDI-_MULT_NOM_20210518234500_20210518235959_4000M_V0001 文件名称（不加后缀）
            if (fileName.contains(".")){
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
            }else {
                fileName = fileName.substring(0, fileName.length() - 4);
            }
            String productType = defaultRequestDto.getBasic().getProductType();
            String subPath = "";
            String execJson="";
            if (StringUtils.isEmpty(productType)) {
                // SWAPDSTDET/FY4A/AGRI/4000/20210518/FY4A-_AGRI--_N_DISK_1047E_L1-_FDI-_MULT_NOM_20210518234500_20210518235959_4000M_V0001
//                subPath = adsType.replace("SWAP", "ADS") + "/" + "FY4A/AGRI/4000/" + fileDate + "/" + fileName;
//                execJson = adsType.replace("SWAP", "ADS") + "/" + "FY4A/AGRI/4000/" + fileDate + "/" +"execJson/"+ fileName;
                subPath = adsType + "/" +  fileDate + "/" + fileName;
                execJson = adsType + "/" + fileDate + "/" +"execJson/"+ fileName;
            } else {
//                subPath = adsType.replace("SWAP", "ADS") + "/" + "FY4A/AGRI/4000/" + fileDate + "/" + fileName + productType;
//                execJson = adsType.replace("SWAP", "ADS") + "/" + "FY4A/AGRI/4000/" + fileDate + "/" +"execJson/"+ fileName+productType;

                subPath = adsType + "/"  + fileDate + "/" + fileName + productType;
                execJson = adsType+ "/"  + fileDate + "/" +"execJson/"+ fileName+productType;
            }

            //将参数部分生成json文件(文件名称为fileTaskID.json)
            execJsonFilePath = String.format("%s/%s.json", dmsClientBean.getAlgorithmBean().getResultLogPath(), execJson);

            exectxtFilePath = String.format("%s/%s.txt", dmsClientBean.getAlgorithmBean().getResultLogPath(), subPath);

            String algorithOutput = dmsClientBean.getAlgorithmBean().getResultJsonPath();
            resultJsonFilePath = String.format("%s/%s.json", dmsClientBean.getAlgorithmBean().getResultLogPath(), subPath);
            resultLogFilePath = String.format("%s/%s.log", dmsClientBean.getAlgorithmBean().getResultLogPath(), subPath);
            resultFlowFilePath = String.format("%s/%s.json", dmsClientBean.getAlgorithmBean().getResultFlowPath(), subPath + "_flow");

            resultJsonFilePath = FilenameUtils.separatorsToUnix(new File(resultJsonFilePath).getAbsolutePath());
            resultLogFilePath = FilenameUtils.separatorsToUnix(new File(resultLogFilePath).getAbsolutePath());
            resultFlowFilePath = FilenameUtils.separatorsToUnix(new File(resultFlowFilePath).getAbsolutePath());
            logger.info(defaultRequestDto.getAlgorithmParameter().getParameter00());
                jsonObject = JSON.parseObject(JSON.toJSONString(defaultRequestDto.getAlgorithmParameter().getParameter01()));
                jsonObject.put("resultPath", (String)json.get("productDir"));
                jsonObject.put("resultJsonFile", resultJsonFilePath);
                jsonObject.put("resultLogFile", resultLogFilePath);
                jsonObject.put("resultFlowFile", resultFlowFilePath);
                try {
                    FileWriteUtil fileWriteUtil = new FileWriteUtil(new File(execJsonFilePath));
                    fileWriteUtil.writeDataValue(jsonObject.toJSONString());
                } catch (Exception e) {
                    logger.error("[文件操作失败] 写算法参数文件时出错!");
                }
                return qsClientRunnerConverter.requestDto2RunnerDto(defaultRequestDto, jsonObject, execJsonFilePath, resultJsonFilePath);
        }else{
            logger.error("[无效算法] 此客户端无此算法!{}",defaultRequestDto.getBasic().getAlgorithmIdentify());
        }
        return qsClientRunnerConverter.requestDto2RunnerDto(defaultRequestDto, paramString, exectxtFilePath, resultJsonFilePath,resultLogFilePath,resultFlowFilePath);
    }

    @Override
    public String spliceCommand(QsClientRunnerDto runnerDto) {
        DMSClientBean dmsClientBean = LocalCache.algorithmCache.get(runnerDto.getAlgorithmIdentify());
        if(dmsClientBean!=null){
            StringBuffer command = new StringBuffer();
            String dockerName = dmsClientBean.getAlgorithmBean().getExecDockerName();
            if(StringUtils.isNotBlank(dockerName)) {
                logger.info(dockerName);
                    if(StringUtils.isNotBlank(runnerDto.getAlgorithmExecFile())){
                        command.append(dmsClientBean.getAlgorithmBean().getExecMainFcnFile()).append(" ").append(runnerDto.getAlgorithmExecFile());
                    }
//                command.insert(0, "echo  \" source ~/.bashrc  &&  sh ");
//                command.append(" \" | docker exec -i "+dockerName+" /bin/bash ");
                command.insert(0, "docker exec -i "+dockerName+" /bin/bash ");
            }
            if(command.length()>0){
                return command.toString();
            }
        }
        return null ;
    }
    public String writeJson(String jsonPath, Map<String, Object> inMap) {
        // Map数据转化为Json，再转换为String
        String data = new JSONObject(inMap).toString();
        File jsonFile = new File(jsonPath);
        try {
            FileWriter fileWriter = new FileWriter(jsonFile.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fileWriter);
            bw.write(data);
            bw.close();
            logger.info("写入成功");
            return "success";
        } catch (IOException e) {
            logger.info("写入失败");
            return "error";
        }
    }

    @Override
    public String spliceResultJson(QsClientRunnerDto runnerDto) {
        String resultJsonFile = runnerDto.getResultJsonFile();
        File resultFile = new File(resultJsonFile);
        if(resultFile.exists()){
            try {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("algorithmResultsJson",resultJsonFile);
                kafkaTemplate.send(xzdyEnterDataTopic,jsonObject.toJSONString());
                String resultStr = FileUtils.readFileToString(resultFile, StandardCharsets.UTF_8);
                QsEnterDataVo qsEnterDataVo = qsEnterDataConverter.runnerDto2EnterDataVo(runnerDto, resultStr);
                JSONObject resultJson = JSON.parseObject(JSON.toJSONString(qsEnterDataVo));
                Object other = runnerDto.getOther();
                JSONObject otherJson = JSONObject.parseObject(JSON.toJSONString(other));
                resultJson.putAll(otherJson);
                return resultJson.toJSONString();
            } catch (Exception e) {
                logger.error("[文件读取失败] 文件地址: {}",resultFile.getAbsolutePath());
            }
        }else{
            logger.error("[结果文件不存在] 文件地址: {}",resultFile.getAbsolutePath());
        }
        return null;
    }

    /**
     * 算法调用结束后置处理
     * 1.将任务从客户端缓存中移除
     * 2.最后一次记录算法生成的运行信息
     * 3.删除无效任务调用文件
     * @param runnerDto 执行对象
     */
    @Override
    public void afterProcess(QsClientRunnerDto runnerDto) {
        //File resultJsonFile = new File(runnerDto.getResultJsonFile());
        //File execFile = new File(runnerDto.getAlgorithmExecFile());
        LocalCache.taskRunnerCache.remove(String.format("%s:%s:%s",runnerDto.getTaskId(),runnerDto.getAlgorithmIdentify(),runnerDto.getFileName()));
        redisSateService.recordStatus(runnerDto,true);
        //resultJsonFile.delete();
        //execFile.delete();
    }
}
